<template>
  <div class="arc-con">
    <div class="scale-btn">
      <span class="add-icon" id="btn_big"
        ><span><img src="~assets/img/map-scale-add.png" alt="" /></span
      ></span>
      <span class="reduce-icon" id="btn_small"
        ><span><img src="~assets/img/map-scale-reduce.png" alt="" /></span
      ></span>
    </div>
    <div id="SceneView" v-loading="loadingMap"></div>
  </div>
</template>

<script>
import { postData } from "@/request/http";
import { loadModules } from "esri-loader";
import PopUp from "./PopUp";
import Vue from "vue";

export default {
  name: "ArcGIS",
  props: {
    name_like: String,
    gfather_name: String,
    father_name: String,
  },

  data() {
    return {
      marker: [],
      marker_icon0: require("@/assets/img/marker-icon0.png"),
      marker_icon1: require("@/assets/img/marker-icon1.png"),
      marker_icon_1: require("@/assets/img/marker-icon-1.png"),
      latitude: baseCenter.lat,
      longitude: baseCenter.lng,
      distance: 60000,
      deleteArr: [],
      layer: null,
      isFirst: true,
      Graphic: null,
      loadingMap: true,
      view: null,
      Point: null,
    };
  },
  async mounted() {
    await this.initMap();
  },
  methods: {
    /*
        获取数据
    */
    async getMarkerData(layer, Graphic) {
      this.loadingMap = true;
      this.marker = [];
      this.Graphic = Graphic;
      postData("/adminweb/device/list/byLocation", {
        latitude: this.latitude,
        longitude: this.longitude,
        distance: this.distance,
      })
        .then(async (res) => {
          if (res.code == 0) {
            var devices = res.datas.devices;

            if (Array.isArray(devices) && devices.length > 0) {
              for (let i = 0; i < devices.length; i++) {
                this.marker.push({
                  longitude: devices[i].location.longitude,
                  latitude: devices[i].location.latitude,
                  attributes: {
                    ...devices[i],
                    ...devices[i].location,
                  },
                });
              }

              let val = this.marker;
              //   await layer.applyEdits({
              //     addFeatures: [],
              //     deleteFeatures: this.deleteArr,
              //   });
              let graphicsLayerGather = []; // 需要在地图上描绘的点位集合
              if (val.length > 0) {
                for (let i = 0; i < val.length; i++) {
                  let point = val[i];
                  let Ghc = new Graphic({
                    attributes: point.attributes,
                    geometry: {
                      type: "point",
                      longitude: point.longitude, //经度
                      latitude: point.latitude, //纬度
                    },
                  });
                  graphicsLayerGather.push(Ghc);
                }
              }
              layer
                .applyEdits({
                  addFeatures: graphicsLayerGather,
                  deleteFeatures: this.deleteArr,
                })
                .then((results) => {
                  // console.log(results);
                  this.loadingMap = false;
                });
              this.deleteArr = graphicsLayerGather;
            }
          } else {
            this.$message.error(res.code + "，" + res.msg);
            this.loadingMap = false;
          }
        })
        .catch((res) => {
          this.$message.error(res.code + "，" + res.msg);
        });
    },

    /*
        搜索
    */
    fnSearch(val) {
      this.marker = [];
      if (Array.isArray(val) && val.length > 0) {
        for (let i = 0; i < val.length; i++) {
          this.marker.push({
            longitude: val[i].location.longitude,
            latitude: val[i].location.latitude,
            attributes: {
              ...val[i],
              ...val[i].location,
            },
          });
        }
      }
      let graphicsLayerGather = []; // 需要在地图上描绘的点位集合
      if (this.marker.length > 0) {
        for (let i = 0; i < this.marker.length; i++) {
          let point = this.marker[i];
          let Graphic = this.Graphic;
          let Ghc = new Graphic({
            attributes: point.attributes,
            geometry: {
              type: "point",
              longitude: point.longitude, //经度
              latitude: point.latitude, //纬度
            },
          });
          graphicsLayerGather.push(Ghc);
        }
      }
      this.view.goTo({
        zoom: 10,
      });
      this.layer
        .applyEdits({
          addFeatures: graphicsLayerGather,
          deleteFeatures: this.deleteArr,
        })
        .then((results) => {
          // console.log(results);
        });
      this.deleteArr = graphicsLayerGather;
    },

    /*
        地图初始化
    */
    initMap() {
      this.loadingMap = true;
      var _that = this;
      //   let options = {
      //     url: "https://js.arcgis.com/4.22/",
      //     css: "https://js.arcgis.com/4.22/esri/themes/light/main.css",
      //   };
      let options = {
        url: "http://10.238.252.73/javascript/api/4.22/init.js",
        css: "http://10.238.252.73/javascript/api/4.22/esri/themes/light/main.css",
      };

      loadModules(
        [
          "esri/Map",
          "esri/views/MapView",
          "esri/layers/TileLayer",
          "esri/PopupTemplate",
          "esri/Graphic",
          "esri/geometry/Point",
          "esri/layers/FeatureLayer",
          "esri/layers/support/Field",
          "esri/widgets/ScaleBar",
          "esri/widgets/Zoom",
          "esri/layers/GraphicsLayer",
          "esri/smartMapping/labels/clusters",
          "esri/smartMapping/popup/clusters",
          "esri/symbols/PictureMarkerSymbol",
          "esri/symbols/SimpleMarkerSymbol",
          "esri/renderers/ClassBreaksRenderer",
        ],
        options
      ).then(
        async ([
          Map,
          MapView,
          TileLayer,
          PopupTemplate,
          Graphic,
          Point,
          FeatureLayer,
          Field,
          Scalebar,
          Zoom,
          GraphicsLayer,
          clusterLabelCreator,
          clusterPopupCreator,
          PictureMarkerSymbol,
          SimpleMarkerSymbol,
          ClassBreaksRenderer,
        ]) => {
          this.Point = Point;
          var map = new Map("map", { logo: false, autoResize: true });
          let view = new MapView({
            container: "SceneView",
            map: map,
            zoom: 11,
          });
          this.view = view;
          //zoom最小最大
          view.constraints = {
            minZoom: 5,
            maxZoom: 10000,
          };
          let layerUrl =
            "http://10.238.252.73:6080/arcgis/rest/services/yongchengdzdt/MapServer";
          let layer = new TileLayer(layerUrl, null);
          map.layers.add(layer);

          //icon
          var uniqueValueInfos = [
            {
              value: "0",
              symbol: {
                type: "picture-marker",
                url: this.marker_icon1,
                width: "18px",
                height: "18px",
              },
            },
            {
              value: "1",
              symbol: {
                type: "picture-marker",
                url: this.marker_icon0,
                width: "18px",
                height: "18px",
              },
            },
            {
              value: "undefined",
              symbol: {
                type: "picture-marker",
                url: this.marker_icon0,
                width: "18px",
                height: "18px",
              },
            },
            {
              value: "-1",
              symbol: {
                type: "picture-marker",
                url: this.marker_icon_1,
                width: "18px",
                height: "18px",
              },
            },
          ];
          const marker_icon = new PictureMarkerSymbol({
            url: this.marker_icon0,
            width: "24px",
            height: "24px",
          });

          const defaultSym = new SimpleMarkerSymbol({
            style: "circle",
            color: "#FF8247",
            size: "8px", // pixels
            outline: {
              color: "#FFD700",
              width: 2, // points
            },
          });
          const defaultSym1 = new SimpleMarkerSymbol({
            style: "circle",
            color: "#EE3B3B",
            size: "8px", // pixels
            outline: {
              color: "#FFD700",
              width: 2, // points
            },
          });
          const defaultSym2 = new SimpleMarkerSymbol({
            style: "circle",
            color: "#A020F0",
            size: "8px", // pixels
            outline: {
              color: "#FFD700",
              width: 2, // points
            },
          });
          const renderer = new ClassBreaksRenderer({
            type: "class-breaks",
            field: "cluster_count",
            defaultSymbol: marker_icon,
            classBreakInfos: [
              { minValue: 2, maxValue: 10, symbol: defaultSym },
              { minValue: 11, maxValue: 50, symbol: defaultSym1 },
              { minValue: 51, maxValue: 10000, symbol: defaultSym2 },
            ],
          });

          var layerFrus = new FeatureLayer({
            id: "deviceLayer",
            title: "设备图层",
            source: [],
            objectIdField: "OBJECTID",
            fields: [
              {
                name: "OBJECTID",
                type: "oid",
              },
              {
                name: "alias",
                type: "string",
              },
              {
                name: "longitude",
                type: "string",
              },
              {
                name: "latitude",
                type: "string",
              },
              {
                name: "sn",
                type: "string",
              },
              {
                name: "online",
                type: "string",
              },
              {
                name: "cluster_count",
                type: "string",
              },
            ],
            outFields: ["*"],
            geometryType: "point",
            popupTemplate: {
              content: "加载中",
            },
            renderer: renderer,
          });
          this.layer = layerFrus;
          map.add(layerFrus);
          this.isFirst = true;

          //点击
          view.on("click", (event) => {
            let self = this;
            view.hitTest(event).then(function (response) {
              if (response.results.length == 0) {
                return;
              }
              let graphic = response.results[0].graphic;
              self.openPopup(
                event.mapPoint,
                graphic,
                view,
                layerFrus,
                PopupTemplate
              );
            });
          });

          //拖拽
          view.on("drag", (event) => {
            if (event.action == "end") {
              if (!this.name_like && !this.gfather_name && !this.father_name) {
                _that.getDistance(view, layerFrus, Graphic, map);
              }
            }
          });

          // 鼠标滑轮-放大缩小
          view.on("mouse-wheel", () => {
            if (!this.name_like && !this.gfather_name && !this.father_name) {
              _that.getDistance(view, layerFrus, Graphic, map);
            }
          });

          // 自定义放大,缩小按钮
          _that.customScale(view, Zoom, layerFrus, Graphic, map);

          // 比例尺
          var scale = new Scalebar({
            view: view,
            unit: "metric",
            style: "ruler",
          });
          view.ui.add(scale, {
            position: "bottom-left",
          });

          //隐藏自带的zoom控件
          view.ui._removeComponents(["zoom"]);

          // 聚合
          this.getMarkerData(layerFrus, Graphic, map);
          layerFrus
            .when()
            .then(generateClusterConfig)
            .then((featureReduction) => {
              layerFrus.featureReduction = isWithinScaleThreshold()
                ? featureReduction
                : null;
              view.watch("scale", () => {
                console.log(view.zoom);
                //marker
                // if (view.zoom >= 14) {
                //   layerFrus.renderer = {
                //     type: "unique-value",
                //     //提取type作为渲染图标类型的标识
                //     valueExpression: `return $feature.online`,
                //     //所有图标类型声明
                //     uniqueValueInfos,
                //   };
                // } else {
                //   //聚合
                //   layerFrus.renderer = {
                //     type: "simple",
                //     symbol: {
                //       type: "simple-marker",
                //       color: "orange",
                //       outline: {
                //         width: 0.5,
                //         color: "white",
                //       },
                //     },
                //   };
                // }
              });
            })
            .catch((error) => {
              console.error(error);
            });

          function isWithinScaleThreshold() {
            return view.scale > 50000;
          }

          async function generateClusterConfig(layer) {
            const { labelingInfo, clusterMinSize } = await clusterLabelCreator
              .getLabelSchemes({ layer, view })
              .then((labelSchemes) => labelSchemes.primaryScheme);
            return {
              type: "cluster",
              labelingInfo,
              clusterMinSize,
              //   popupTemplate: {
              //     title: "",
              //     content: "该模块包括 {cluster_count} 点.",
              //     fieldInfos: [
              //       {
              //         fieldName: "cluster_count",
              //         format: {
              //           places: 0,
              //           digitSeparator: true,
              //         },
              //       },
              //     ],
              //   },
            };
          }
        }
      );
    },

    // 计算缩放，并emit事件
    async getDistance(view, layer, Graphic, map) {
      var zoom = view.zoom;
      this.isFirst = false;
      this.zoom = zoom;
      //layerFrus.applyEdits({ addFeatures: [] });
      var multiple = 3;
      var distance;
      if (zoom >= 8 && zoom < 9) {
        distance = 50 * 1000 * multiple;
      } else if (zoom >= 9 && zoom < 10) {
        distance = 25 * 1000 * multiple;
      } else if (zoom >= 10 && zoom < 11) {
        distance = 20 * 1000 * multiple;
      } else if (zoom >= 11 && zoom < 12) {
        distance = 10 * 1000 * multiple;
      } else if (zoom >= 12 && zoom < 13) {
        distance = 5 * 1000 * multiple;
      } else if (zoom >= 13 && zoom < 14) {
        distance = 2 * 1000 * multiple;
      } else if (zoom >= 14 && zoom < 15) {
        distance = 1 * 1000 * multiple;
      } else if (zoom >= 15 && zoom < 16) {
        distance = 500 * multiple;
      } else if (zoom >= 16 && zoom < 17) {
        distance = 200 * multiple;
      } else if (zoom >= 17 && zoom < 18) {
        distance = 100 * multiple;
      } else if (zoom >= 18 && zoom < 19) {
        distance = 50 * multiple;
      } else if (zoom >= 19) {
        distance = 20 * multiple;
      } else if (zoom < 8) {
        distance = 50 * 1000 * multiple;
      }
      this.latitude = view.center.y.toFixed(6);
      this.longitude = view.center.x.toFixed(6);
      this.distance = distance;
      await this.getMarkerData(layer, Graphic, map);
      await console.log(this.marker.length);

      // console.log(zoom, distance);
      //   this.$emit("getCenter", {
      //     lat: view.center.y.toFixed(6),
      //     lng: view.center.x.toFixed(6),
      //     distance: distance,
      //     zoom: zoom,
      //   });
    },

    // 自定义放大缩小
    customScale(view, Zoom, layer, Graphic, map) {
      var _that = this;
      var myZoom = new Zoom({
        view: view,
        visible: false,
      });
      const btn_big = document.getElementById("btn_big");
      btn_big.addEventListener("click", () => {
        if (this.loadingMap) {
          return;
        }
        myZoom.zoomIn();

        if (!this.name_like && !this.gfather_name && !this.father_name) {
          _that.getDistance(view, layer, Graphic, map);
        }
      });

      // 自定义-缩小
      const btn_small = document.getElementById("btn_small");
      btn_small.addEventListener("click", () => {
        if (this.loadingMap) {
          return;
        }
        myZoom.zoomOut();
        if (!this.name_like && !this.gfather_name && !this.father_name) {
          _that.getDistance(view, layer, Graphic, map);
        }
      });
    },

    //弹窗
    openPopup(point, graphic, view, layerFrus, PopupTemplate) {
      // 要素中的属性对象 graphic.attributes
      let sn = graphic.attributes.sn;
      let alias = graphic.attributes.alias;
      let longitude = graphic.attributes.longitude;
      let latitude = graphic.attributes.latitude;
      let online = graphic.attributes.online;
      const p = Vue.extend(PopUp);
      // console.log(sn, alias, longitude);
      let vm = new p({
        el: document.createElement("div"),
        data: {
          sn: sn,
          alias: alias,
          longitude: longitude,
          latitude: latitude,
          online: online,
        },
      });
      vm.$nextTick(() => {
        const template = new PopupTemplate({
          content: vm.$el,
          overwriteActions: true,
        });
        layerFrus.popupTemplate = template;
      });
    },
  },
  components: {
    PopUp,
  },
};
</script>
<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.arc-con {
  position: relative;
}
#SceneView {
  width: 100%;
  height: calc(100vh - 140px);
}
#box1 {
  width: 100vw;
  height: 20vh;
}
.esri-popup__main-container {
  max-height: 500px !important;
}
.el-card__body {
  padding: 0 !important;
}
.scale-btn {
  position: absolute;
  left: 20px;
  top: 20px;
  z-index: 9999;
  display: flex;
  flex-flow: column;
}
.esri-view-root {
  background: #d9dcdd !important;
}
.esri-ui .esri-popup {
  border-radius: 10px;
}
.esri-view-width-xlarge .esri-popup__main-container {
  min-height: 390px !important;
  border-radius: 10px;
}
</style>
